#include "stdafx.h"
#include "net/ICMPEventArgs.hpp"
#include "net/DNS.hpp"
#include <numeric>

NET_NAMESPACE_BEGIN

CICMPEventArgs::CICMPEventArgs(const CSocketAddress& address, int repetitions, int dataSize, int ttl)
	: m_address(address), 
	m_sent(0),
	m_dataSize(dataSize), 
	m_ttl(ttl), 
	m_rtt(repetitions, 0), 
	m_errors(repetitions)
{
}

CICMPEventArgs::~CICMPEventArgs()
{
}

std::string CICMPEventArgs::hostName() const
{
	try
	{
		return CDNS::resolve(m_address.host().toString()).name();
	}
	catch (HostNotFoundException&) 
	{
	}
	catch (NoAddressFoundException&) 
	{
	}
	catch (DNSException&)
	{
	}
	catch (IOException&)
	{
	}
	return m_address.host().toString();
}

std::string CICMPEventArgs::hostAddress() const
{
	return m_address.host().toString();
}

void CICMPEventArgs::setRepetitions(int repetitions)
{
	m_rtt.clear();
	m_rtt.resize(repetitions, 0);
	m_errors.assign(repetitions, "");
}

CICMPEventArgs& CICMPEventArgs::operator ++ ()
{
	++m_sent;
	return *this;
}

CICMPEventArgs CICMPEventArgs::operator ++ (int)
{
	CICMPEventArgs prev(*this);
	operator ++ ();
	return prev;
}

int CICMPEventArgs::received() const
{
	int received = 0;

	for (size_t i = 0; i < m_rtt.size(); ++i) 
	{
		if (m_rtt[i]) ++received;
	}
	return received;
}

void CICMPEventArgs::setError(int index, const std::string& text)
{
	if (index >= (int)m_errors.size()) 
		throw InvalidArgumentException("Supplied index exceeds vector capacity.");

	m_errors[index] = text;
}

const std::string& CICMPEventArgs::error(int index) const
{
	if (0 == m_errors.size()) 
		throw InvalidArgumentException("Supplied index exceeds vector capacity.");

	if (-1 == index) index = m_sent - 1;

	return m_errors[index];
}

void CICMPEventArgs::setReplyTime(int index, int time)
{
	if (index >= (int)m_rtt.size()) 
		throw InvalidArgumentException("Supplied index exceeds array capacity.");
	if (0 == time) time = 1;
	m_rtt[index] = time;
}

int CICMPEventArgs::replyTime(int index) const
{
	if (0 == m_rtt.size()) 
		throw InvalidArgumentException("Supplied index exceeds array capacity.");

	if (-1 == index) index = m_sent - 1;

	return m_rtt[index];
}

int CICMPEventArgs::avgRTT() const
{
	if (0 == m_rtt.size()) return 0;

	return (int) (std::accumulate(m_rtt.begin(), m_rtt.end(), 0) / m_rtt.size());
}

float CICMPEventArgs::percent() const
{
	if (0 == m_rtt.size()) return 0;

	return ((float) received() / (float) m_rtt.size()) * (float) 100.0;
}

NET_NAMESPACE_END
